package com.hanxiaozhang.no2thread;

/**
 * 〈一句话功能简述〉<br>
 * 〈〉
 *
 * @author hanxinghua
 * @create 2022/5/6
 * @since 1.0.0
 */
public class No2Example {

    public static void main(String[] args) {
        //1、先创建一个LockObject对象
        LockObject lockObject = new LockObject(0);
        //2、创建10个线程的数组
        MyThread[] myThread = new MyThread[10];
        //初始化线程并且启动，
        //为了证明线程琐的作用，线程从后面开始启动
        for (int i = 0; i < 10; i++) {
            myThread[i] = new MyThread(lockObject, 9 - i);
            //启动线程  注意继承Thread类是调用start方法，实现Runable接口是调用run方法
            myThread[i].start();
        }
    }
}

/**
 * 线程
 */
class MyThread extends Thread {

    // 1、定义需要传入的LockObject对象
    private LockObject lockObject;

    // 2、定义属于线程自己的打印数字
    private int printNum = 0;

    public MyThread(LockObject lockObject, int printNum) {
        this.lockObject = lockObject;
        this.printNum = printNum;
    }

    @Override
    public void run() {

        // 1、判断该资源是否被占用
        synchronized (lockObject) {
            // 2、如果资源空闲，则判断是否已经打印完成
            while (lockObject.orderNum <= lockObject.MaxValue) {
                // 3、没有打印完则判断是否是自己需要打印的数字
                if (lockObject.orderNum == printNum) {
                    System.out.print(printNum);
                    lockObject.orderNum++;
                    if (lockObject.orderNum == 10) {
                        System.out.println("线程打印完毕");
                    }
                    // 打印完毕后，唤醒所有的线程
                    lockObject.notifyAll();
                } else {
                    // 4、不是该线程打印的数字，则继续等待
                    try {
                        lockObject.wait();
                        // System.out.println("线程等待 "+printNum);
                    } catch (InterruptedException e) {

                        System.out.println("线程" + printNum + "被打断了");
                        e.printStackTrace();
                    }

                }
            }
        }

    }

}

/**
 * 对象锁
 */
class LockObject {

    public int orderNum = 0;

    public final int MaxValue = 9;

    public LockObject(int orderNum) {
        this.orderNum = orderNum;
    }
}